package com.party.mobile.web.controller.pay;

import com.alibaba.fastjson.JSONObject;
import com.google.common.base.Strings;
import com.party.authorization.annotation.Authorization;
import com.party.common.constant.Constant;
import com.party.common.constant.WechatConstant;
import com.party.common.utils.BigDecimalUtils;
import com.party.common.utils.PartyCode;
import com.party.core.model.WechatPayCode;
import com.party.core.model.WechatPayConstant;
import com.party.core.model.commune.CMemberIntegralCount;
import com.party.core.model.mall.MallOrderForm;
import com.party.core.model.order.OrderForm;
import com.party.core.model.order.OrderStatus;
import com.party.core.model.order.PaymentState;
import com.party.core.model.order.PaymentWay;
import com.party.core.model.wechat.WechatMerchants;
import com.party.core.model.wechatPlatform.WechatOpenMember;
import com.party.core.service.commune.ICMemberIntegralCountService;
import com.party.core.service.mall.IMallOrderFormService;
import com.party.core.service.order.IOrderFormInfoService;
import com.party.core.service.order.IOrderFormService;
import com.party.core.service.wechatPlatform.IWechatMerchantService;
import com.party.core.service.wechatPlatform.IWechatOpenMemberService;
import com.party.mobile.biz.currentUser.CurrentUserBizService;
import com.party.mobile.biz.mall.MallOrderBizService;
import com.party.mobile.biz.order.OrderBizNewService;
import com.party.mobile.biz.wechat.WechatOpenMemberBizService;
import com.party.mobile.biz.wechat.WechatPayBizService;
import com.party.mobile.web.dto.AjaxResult;
import com.party.mobile.web.dto.login.output.CurrentUser;
import com.party.mobile.web.dto.pay.output.PayParam;
import com.party.mobile.web.dto.wechat.input.UnifiedOrderResponse;
import com.party.mobile.web.dto.wechat.output.NotifyResponse;
import com.party.mobile.web.dto.wechat.output.PayRequest;
import com.party.mobile.web.dto.wechat.output.UnifiedOrderRequest;
import com.party.mobile.web.utils.VerifyCodeUtils;
import com.party.mobile.web.utils.WechatPayUtils;
import com.party.pay.model.pay.wechat.NotifyRequest;
import org.redisson.api.RLock;
import org.redisson.api.RedissonClient;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 此类描述的是：微信微网站支付控制层
 *
 * @author: Administrator
 * @version: 2017年2月4日 下午6:25:48
 */
@Controller
@RequestMapping(value = "/pay/wechat/wwz")
public class PayWechatWwzController {

    protected static Logger logger = LoggerFactory.getLogger(PayWechatWwzController.class);
    @Autowired
    private IOrderFormService orderFormService;
    @Autowired
    private IMallOrderFormService mallOrderFormService;
    @Autowired
    private WechatPayBizService wechatPayBizService;
    @Autowired
    private IOrderFormInfoService orderFormInfoService;
    @Autowired
    private OrderBizNewService orderBizNewService;
    @Autowired
    private IWechatMerchantService wechatMerchantService;
    @Autowired
    private IWechatOpenMemberService wechatOpenMemberService;
    @Autowired
    private WechatOpenMemberBizService wechatOpenMemberBizService;

    @Autowired
    private ICMemberIntegralCountService integralCountService;
    @Autowired
    private CurrentUserBizService currentUserBizService;
    @Autowired
    private MallOrderBizService mallOrderBizService;

    @Autowired
    private RedissonClient redissonClient;
    // 公众号回调地址
    @Value("#{pay_wechat_wwz['wechat.wwz.notifyUrl']}")
    private String notifyUrl;


    @Authorization
    @ResponseBody
    @RequestMapping(value = "/integral")
    public AjaxResult payByIntegral(String orderId, HttpServletRequest request) {
        // 数据验证
        if (Strings.isNullOrEmpty(orderId)) {
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "订单号不能为空");
        }

        // 订单验证
        MallOrderForm orderForm = mallOrderFormService.get(orderId);
        if (null == orderForm) {
            return AjaxResult.error(PartyCode.ORDER_UNEXIST, "订单不存在");
        }

        // 订单状态验证
        if (!orderForm.getIsPay().equals(PaymentState.NO_PAY.getCode()) ||
                !orderForm.getStatus().equals(OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode())) {
            return AjaxResult.error(PartyCode.PAYMENT_STATUS_ERROR, "订单状态不正确");
        }
        CurrentUser currentUser = currentUserBizService.getCurrentUser(request);
        CMemberIntegralCount memberIntegralCount = integralCountService.getByMemberId(currentUser.getId());

        //获取会员可用积分
        Double availableIntegral = memberIntegralCount.getAvailableIntegral();
        if (availableIntegral < orderForm.getPayment()) {
            return AjaxResult.error(Integer.valueOf("10001"),"积分不够！");
        }

        if (OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode().equals(orderForm.getStatus())) {
            // 支付订单
            RLock lock = redissonClient.getLock("PayWechatWwzController");
            try {
                lock.lock(); //（默认是30秒自动过期）
                logger.info(orderForm.getId() + "Request Thread - " + Thread.currentThread().getName() + " 加锁...");
                mallOrderBizService.updatePayBusiness(orderForm,memberIntegralCount, PaymentWay.INTEGRAL_PAY.getCode());
            } catch (Exception e) {
                logger.error("积分兑换订单支付异常", e);
                return AjaxResult.error(Integer.valueOf(500),"积分兑换失败");
            } finally {
                lock.unlock();
                logger.info(orderForm.getId() + "Request Thread - " + Thread.currentThread().getName() + " 解锁...");
            }
        }
        return AjaxResult.success();
    }

    @Authorization
    @ResponseBody
    @RequestMapping(value = "/getPayData")
    public AjaxResult getPayData(String orderId, String openId, HttpServletRequest request) {
        // 数据验证
        if (Strings.isNullOrEmpty(orderId)) {
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "订单号不能为空");
        }

        if (Strings.isNullOrEmpty(openId)) {
            return AjaxResult.error(PartyCode.PARAMETER_ILLEGAL, "缺少支付参数 openId");
        }

        // 订单验证
        OrderForm orderForm = orderFormService.get(orderId);
        if (null == orderForm) {
            return AjaxResult.error(PartyCode.ORDER_UNEXIST, "订单不存在");
        }

        PayParam payParam = wechatOpenMemberBizService.getPayData(orderForm);

        // 订单状态验证
        if (!orderForm.getIsPay().equals(PaymentState.NO_PAY.getCode()) || !orderForm.getStatus().equals(OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode())) {
            return AjaxResult.error(PartyCode.PAYMENT_STATUS_ERROR, "订单状态不正确");
        }
        // 统一下单
        String nonceStr = VerifyCodeUtils.RandomString(WechatConstant.RANDOM_LENGTH);// 获取随机数
        String ipAddress = request.getRemoteAddr();// 终端IP

        UnifiedOrderRequest unifiedOrderRequest = new UnifiedOrderRequest();

        String body = wechatPayBizService.subTitle(orderForm.getTitle(), 125);
        unifiedOrderRequest.setBody(body);// 商品描叙

        unifiedOrderRequest.setAppid(payParam.getAppId());// 公众账号ID
        unifiedOrderRequest.setMchId(payParam.getMchId());// 商户编号
        unifiedOrderRequest.setOpenid(openId);// 用户编号
        unifiedOrderRequest.setNonceStr(nonceStr);// 随机数
        unifiedOrderRequest.setOutTradeNo(orderForm.getId());// 订单号
        double total = BigDecimalUtils.mul(orderForm.getPayment(), 100);
        total = BigDecimalUtils.round(total, 2);
        unifiedOrderRequest.setTotalFee((int) total);// 单位分
        unifiedOrderRequest.setSpbillCreateIp(ipAddress);// 请求IP
        unifiedOrderRequest.setNotifyUrl(notifyUrl);// 回调地址
        unifiedOrderRequest.setTradeType(WechatConstant.TRADE_TYPE);// 交易类型
        UnifiedOrderResponse unifiedorderResponse = wechatPayBizService.unifiedOrder(unifiedOrderRequest, payParam.getApiKey());
        if (null == unifiedorderResponse ||
                !Constant.WECHAT_SUCCESS.equals(unifiedorderResponse.getReturnCode()) ||
                !Constant.WECHAT_SUCCESS.equals(unifiedorderResponse.getResultCode())) {
            return AjaxResult.error(PartyCode.UNIFIEDORDER_ERROR, "微信统一下单异常");
        }
        if (Constant.WECHAT_SUCCESS.equals(unifiedorderResponse.getReturnCode()) && Constant.WECHAT_SUCCESS.equals(unifiedorderResponse.getResultCode())) {
            // 平台
            orderForm.setTradeType(Constant.CLIENT_WX_WWZ);
            // 商户号
            orderForm.setMerchantId(payParam.getMchId());
            // 支付类型
            orderForm.setPaymentWay(PaymentWay.WECHAT_PAY.getCode());
            orderFormService.update(orderForm);

            // 保存订单附属信息
            orderFormInfoService.saveOrderFormInfo(payParam.getAppId(), payParam.getMchId(), payParam.getApiKey(), orderForm.getId());
        }

        // 发起下单
        String prepayId = unifiedorderResponse.getPrepayId();
        PayRequest payRequest = new PayRequest();
        payRequest.setAppId(payParam.getAppId());// 开放平台编号
        payRequest.setTimeStamp(String.valueOf(System.currentTimeMillis()));// 时间戳
        payRequest.setNonceStr(nonceStr);// 随机数
        payRequest.setPackages(WechatConstant.PREPAY_ID + prepayId);// 预授权码
        payRequest.setSignType(WechatConstant.MD5_TYPE);// 加密方式

        // 获取签名
        logger.info("微信支付--获取参数列表", JSONObject.toJSON(payRequest)+"___apiKey:"+payParam.getApiKey());
        String sign = WechatPayUtils.getSign(payRequest, payParam.getApiKey());
        payRequest.setPaySign(sign);

        logger.info("微信微网站发起支付请求参数:{}", JSONObject.toJSON(payRequest));
        return AjaxResult.success(payRequest);
    }

    @ResponseBody
    @RequestMapping(value = "/testOrder")
    public AjaxResult testOrder(String wechatOpenMemberId, String wechatMerchantId, String openId, Double money, HttpServletRequest request) {

//		money = 0.01;
//		openId = "osScduKzcdCOVhp71YDJUgndzFtU";
//		wechatMerchantId = "c29f97c3ce0d4f18a227d308a5ad8adf";
//		wechatOpenMemberId = "28a9bc6b1e44427db356bdfeaeafee2e";

        String ipAddress = request.getRemoteAddr();// 终端IP

//		ipAddress = "119.137.55.205";

        WechatOpenMember wechatOpenMember = wechatOpenMemberService.get(wechatOpenMemberId);
        if (null == wechatOpenMember || null == wechatOpenMember.getAuthorizerAppid()) {
            return AjaxResult.error(WechatPayCode.NO_SUCH_WECHAT_OPEN_MEMBER, "系统找不到该公众号, 请重新配置微信账号或者授权");
        }
        String appId = wechatOpenMember.getAuthorizerAppid();
        WechatMerchants wechatMerchants = wechatMerchantService.get(wechatMerchantId);
        if (null == wechatMerchants || null == wechatMerchants.getMerchantId()) {
            return AjaxResult.error(WechatPayCode.NO_SUCH_WECHAT_MERCHANT, "系统找不到该商户号, 请重新配置微信商户");
        }
        String merchantId = wechatMerchants.getMerchantId();

        String nonceStr = VerifyCodeUtils.RandomString(WechatConstant.RANDOM_LENGTH);// 获取随机数

        UnifiedOrderRequest unifiedOrderRequest = new UnifiedOrderRequest();

        String body = wechatPayBizService.subTitle("测试appId{appId}AA0AAmerchantId{merchantId}AA0AAopenId{openId}".
                replace("{appId}", appId).replace("{merchantId}", merchantId).
                replace("{openId}", openId), 125);
        if (body.length() > 128) {
            body = body.substring(0, 127);
        }
        unifiedOrderRequest.setBody(body);// 商品描叙
        unifiedOrderRequest.setAppid(appId);// 公众账号ID
        unifiedOrderRequest.setMchId(merchantId);// 商户编号
        unifiedOrderRequest.setOpenid(openId);// 用户编号
        unifiedOrderRequest.setNonceStr(nonceStr);// 随机数

        // 生成随机的微信后台统一下单订单号
        String testOrderId = "test" + System.currentTimeMillis() + VerifyCodeUtils.RandomString(10);
        logger.info("测试支付的微信统一下单的单号testOrderId = {}", testOrderId);

        unifiedOrderRequest.setOutTradeNo(testOrderId);// 订单号

        double total = BigDecimalUtils.mul(money, 100);
        total = BigDecimalUtils.round(total, 2);
        unifiedOrderRequest.setTotalFee((int) total);// 单位分

        unifiedOrderRequest.setSpbillCreateIp(ipAddress);// 请求IP

        unifiedOrderRequest.setNotifyUrl(notifyUrl);// 回调地址
        unifiedOrderRequest.setTradeType(WechatConstant.TRADE_TYPE);// 交易类型
        UnifiedOrderResponse unifiedorderResponse = wechatPayBizService.unifiedOrder(unifiedOrderRequest, wechatMerchants.getMerchantApiKey());
        if (null == unifiedorderResponse) {
            return AjaxResult.error(PartyCode.UNIFIEDORDER_ERROR, "测试支付的微信统一下单异常");
        }

        // 失败的各种情况
        if (WechatPayConstant.FAIL.equals(unifiedorderResponse.getReturnCode())) {
            if (WechatPayConstant.MERCHANT_NOT_EXIST.equals(unifiedorderResponse.getReturnMsg())) {
                return AjaxResult.error(WechatPayCode.MERCHANT_ID_IS_WRONG, "商户号id错误, 请重新配置微信商户");
            } else if (WechatPayConstant.MERCHANT_APP_NOT_MATCH.equals(unifiedorderResponse.getReturnMsg())
                    || WechatPayConstant.MERCHANT_APPID_NOT_MATCH.equals(unifiedorderResponse.getReturnMsg())) {
                return AjaxResult.error(WechatPayCode.MERCHANT_APP_NOT_MATCH, "商户号与公众号不匹配, 请选择其他商户或重新配置微信商户");
            } else if (WechatPayConstant.SIGN_IS_WRONG.equals(unifiedorderResponse.getReturnMsg())) {
                return AjaxResult.error(WechatPayCode.SIGN_IS_WRONG, "签名错误, 请检查商户号ApiKey是否配置正确");
            } else if (WechatPayConstant.NOT_PRIVILEGE.equals(unifiedorderResponse.getReturnMsg())) {
                return AjaxResult.error(WechatPayCode.MERCHANT_NOT_PRIVILEGE, "商户号该产品权限未开通，请去产品中心检查\"JSAPI支付\"是否开通");
            } else {
                logger.error("测试支付的微信统一下单异常, {}", JSONObject.toJSONString(unifiedorderResponse));
                return AjaxResult.error(PartyCode.UNIFIEDORDER_ERROR, "测试支付的微信统一下单异常------" + unifiedorderResponse.getReturnMsg());
            }
        }

        if (WechatConstant.SUCCESS.equals(unifiedorderResponse.getReturnCode())) {
            System.out.println(testOrderId);
        }

        // 发起下单
        String prepayId = unifiedorderResponse.getPrepayId();
        PayRequest payRequest = new PayRequest();
        payRequest.setAppId(appId);// 开放平台编号
        payRequest.setTimeStamp(String.valueOf(System.currentTimeMillis()));// 时间戳
        payRequest.setNonceStr(nonceStr);// 随机数
        payRequest.setPackages(WechatConstant.PREPAY_ID + prepayId);// 预授权码
        payRequest.setSignType(WechatConstant.MD5_TYPE);// 加密方式

        // 获取签名
        String sign = WechatPayUtils.getSign(payRequest, wechatMerchants.getMerchantApiKey());
        payRequest.setPaySign(sign);

        logger.info("微信微网站发起支付请求参数:{}", JSONObject.toJSON(payRequest));
        return AjaxResult.success(payRequest);
    }

    /**
     * 获取微信支付异步通知 测试
     *
     * @param orderId 订单id
     * @return 返回参数
     */
    @ResponseBody
    @RequestMapping("acceptNotify2")
    public void acceptNotify2(String orderId, HttpServletResponse response) throws IOException {
        OrderForm orderForm = orderFormService.get(orderId);

        if (OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode().equals(orderForm.getStatus())) {
            // 支付订单
            RLock lock = redissonClient.getLock("PayWechatWwzController");
            try {
                lock.lock(); //（默认是30秒自动过期）
                logger.info(orderForm.getId() + "Request Thread - " + Thread.currentThread().getName() + " 加锁...");
                orderBizNewService.updatePayBusiness(orderForm, null, PaymentWay.WECHAT_PAY.getCode());
            } catch (Exception e) {
                logger.error("订单支付异常", e);
                writeResult(response, NotifyResponse.error("同行者支付失败"));
                return;
            } finally {
                lock.unlock();
                logger.info(orderForm.getId() + "Request Thread - " + Thread.currentThread().getName() + " 解锁...");
            }
        }
        writeResult(response, NotifyResponse.success());
    }

    /**
     * 获取微信支付异步通知
     *
     * @param request 请求参数
     * @return 返回参数
     */
    @ResponseBody
    @RequestMapping("acceptNotify")
    public void acceptNotify(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String requestStr = wechatPayBizService.getNotifyXml(request);
        logger.info("微网站获取微信支付异步通知数据:{}", requestStr);
        if (Strings.isNullOrEmpty(requestStr)) {
            writeResult(response, NotifyResponse.error("请求参数为空"));
            return;
        }
        NotifyRequest notifyRequest;
        try {
            notifyRequest = WechatPayUtils.deserialize(requestStr, NotifyRequest.class);
        } catch (Exception streamExceptione) {
            logger.error("微网站微信支付异步通知解析异常", streamExceptione);
            writeResult(response, NotifyResponse.error("报文解析异常"));
            return;
        }

        OrderForm orderForm = orderFormService.get(notifyRequest.getOutTradeNo());

        PayParam payParam = wechatOpenMemberBizService.getPayData(orderForm);

        // 验证数据安全
        boolean verify = wechatPayBizService.verify(notifyRequest, payParam.getApiKey(), payParam.getAppId(), payParam.getMchId());
        if (!verify) {
            writeResult(response, NotifyResponse.error("安全验证不通过"));
            return;
        }

        // 支付结果验证
        if ((!WechatConstant.SUCCESS.equals(notifyRequest.getReturnCode()))
                || (!WechatConstant.SUCCESS.equals(notifyRequest.getResultCode()))) {
            writeResult(response, NotifyResponse.error("支付结果不成功"));
            return;
        }

        if (OrderStatus.ORDER_STATUS_TO_BE_PAID.getCode().equals(orderForm.getStatus())) {
            // 支付订单
            RLock lock = redissonClient.getLock("PayWechatWwzController");
            try {
                lock.lock(); //（默认是30秒自动过期）
                logger.info(orderForm.getId() + "Request Thread - " + Thread.currentThread().getName() + " 加锁...");
                orderBizNewService.updatePayBusiness(orderForm, notifyRequest, PaymentWay.WECHAT_PAY.getCode());
            } catch (Exception e) {
                logger.error("订单支付异常", e);
                writeResult(response, NotifyResponse.error("同行者支付失败"));
                return;
            } finally {
                lock.unlock();
                logger.info(orderForm.getId() + "Request Thread - " + Thread.currentThread().getName() + " 解锁...");
            }
        }
        writeResult(response, NotifyResponse.success());
    }

    public void writeResult(HttpServletResponse response, NotifyResponse notifyResponse) throws IOException {
        String responeData = wechatPayBizService.responseNotify(notifyResponse);
        response.getWriter().write(responeData);
        response.getWriter().close();
    }
}
